package com.cqc.manage.service.Imp.business;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.mail.MailUtil;
import com.cqc.manage.dto.BusinessDto;
import com.cqc.manage.dto.EngineerBussinessDto;
import com.cqc.manage.entity.Business;
import com.cqc.manage.entity.CostStatistics;
import com.cqc.manage.entity.MessageBusiness;
import com.cqc.manage.repositories.CostStatisticsRepositories;
import com.cqc.manage.repositories.MessageBusinessRepositories;
import com.cqc.manage.util.BaseValue;
import com.cqc.manage.util.thrift.TTSocket;
import com.cqc.manage.util.thrift.ThriftClientConnectPoolFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Configuration      //1.主要用于标记配置类，兼备Component的效果。
@EnableScheduling
public class BusinessInvoiceService {

    private Logger LOG = LoggerFactory.getLogger(BusinessInvoiceService.class);

    @Autowired
    private ThriftClientConnectPoolFactory thriftClientConnectPoolFactory;

    @Autowired
    private MessageBusinessRepositories messageBusinessRepositories;

    @Autowired
    private CostStatisticsRepositories costStatisticsRepositories;


    /**
     * 获取业务的发票信息
     * @param contractNo
     */
    public void getInvoiceMessage(String contractNo){
        TTSocket ttSocket = null;
        try {
            ttSocket = thriftClientConnectPoolFactory.getConnect();

            List<Map<String, String>> businvoice = ttSocket.getService().getBusinvoice(contractNo);

            LOG.info("查询信息：{}",businvoice);
            thriftClientConnectPoolFactory.returnConnection(ttSocket);

            return;
        }catch (Exception e){
            LOG.error(e.getMessage());
        }
    }

    /**
     * 通过工程师名称查询工程师的所有业务，并保存数据库
     * @param
     */
    @Scheduled(cron = "0 0 20 * * ?")
    public void getEngineerBusinessInvoice(){
        for (String engLism: BaseValue.getEngnameLims()){
            MessageBusiness byContractNo = null;
            TTSocket ttSocket = null;
            try {
                ttSocket = thriftClientConnectPoolFactory.getConnect();
                List<String> all = messageBusinessRepositories.getAllContractNo(engLism);
                List<Map<String, String>> engineerBusiness = ttSocket.getService().getUserNameBusiness(engLism);  // 获取工程师所有的业务
                for (Map<String,String> map:engineerBusiness){
                    Date startDate = DateUtil.parse(map.get("委托日期"));
                    if (DateUtil.year(startDate) >= 2020 ){
                        String contractNo = map.get("合同编号");
                        if (all.contains(map.get("合同编号").trim())) {
                            LOG.info("合同编号:{}",map.get("合同编号"));
                            try{
                                byContractNo = messageBusinessRepositories.findByContractNoAndEngineer(contractNo,engLism);
                            }catch (Exception e){
                                System.err.println("通过工程师名称查询工程师的所有业务，并保存数据库:"+e.getMessage());
                                LOG.error(map.get("合同编号"));
                                continue;
                            }
                            List<Map<String, String>> businvoice = ttSocket.getService().getBusinvoice(contractNo);   // 查询单个业务的发票
                            LOG.info("{}，发票信息：{}",contractNo,businvoice);
                            List<Map<String, String>> businessAgreementAmount = ttSocket.getService().getBusinessAgreementAmount(contractNo);
                            LOG.info("{},协议金额信息：{}",contractNo,businessAgreementAmount);
                            String agreementAmount = businessAgreementAmount.get(0).get("费用");
                            if (businvoice.size() != 0){
                                if (Float.valueOf(businvoice.get(0).get("发票金额")) > 0){
                                    byContractNo.setAgreementAmount(agreementAmount);
                                    byContractNo.setInvoice(businvoice.get(0).get("发票金额"));
                                    messageBusinessRepositories.save(byContractNo);
                                }
                            }else {
                                try{
                                    byContractNo.setAgreementAmount(agreementAmount);
                                    byContractNo.setInvoice("0.0");
                                    messageBusinessRepositories.save(byContractNo);
                                }catch (Exception e){
                                    System.err.println(engLism+"----"+map.get("合同编号"));
                                    e.printStackTrace();
                                }
                            }
                        }else {
                            List<Map<String, String>> businvoice = ttSocket.getService().getBusinvoice(contractNo);   // 查询单个业务的发票
                            LOG.info("{}，发票信息：{}",contractNo,businvoice);
                            List<Map<String, String>> businessAgreementAmount = ttSocket.getService().getBusinessAgreementAmount(contractNo);
                            LOG.info("{},协议金额信息：{}",contractNo,businessAgreementAmount);
                            String agreementAmount = businessAgreementAmount.get(0).get("费用");
//                    String businessinvoice = businvoice.get(0).get("发票金额");
                            if (businvoice.size() != 0){
                                if (Float.valueOf(businvoice.get(0).get("发票金额")) > 0){
                                    MessageBusiness messageBusiness = setBusinessInvoiceData(map, businvoice.get(0).get("发票金额"),engLism,agreementAmount);
                                    messageBusinessRepositories.save(messageBusiness);
                                }
                            }else {
                                MessageBusiness messageBusiness = setBusinessInvoiceData(map, "0.0",engLism,agreementAmount);
                                messageBusinessRepositories.save(messageBusiness);
                            }
                        }
                    }else {
                        System.err.println(map.get("委托日期"));
                    }
                }
                thriftClientConnectPoolFactory.returnConnection(ttSocket);
//                MailUtil.send("1054117754@qq.com", "同步成功", "通过工程师名称查询工程师的所有业务，并保存数据库", false);
            }catch (Exception e){
                e.printStackTrace();
                messageBusinessRepositories.deleteByEngineer(engLism);
                if (ttSocket != null){
                    thriftClientConnectPoolFactory.invalidateObject(ttSocket);
                }
//                MailUtil.send("1054117754@qq.com", e.getMessage(), "通过工程师名称查询工程师的所有业务，并保存数据库", false);
            }
        }

    }

    /**
     * 设置MessageBusiness业务数据
     * @param engineerBusines
     * @param businvoice
     * @param engineerusername
     * @return
     */
    public MessageBusiness setBusinessInvoiceData(Map<String,String> engineerBusines,String businvoice,String engineerusername,String AgreementAmount){
        try {
            MessageBusiness messageBusiness = new MessageBusiness();
            messageBusiness.setClient(engineerBusines.get("委托单位"));
            messageBusiness.setContractNo(engineerBusines.get("合同编号"));
            messageBusiness.setInvoice(businvoice);
            String replace = UUID.randomUUID().toString().replace("-", "");
            messageBusiness.setId(replace);
            messageBusiness.setEndDate(DateUtil.parse(engineerBusines.get("任务到期日期"), "yyyy-MM-dd"));
            messageBusiness.setStartDate(DateUtil.parse(engineerBusines.get("委托日期"), "yyyy-MM-dd"));
            messageBusiness.setStandard(engineerBusines.get("标准"));
            messageBusiness.setReportType(engineerBusines.get("报告类型"));
            messageBusiness.setSampleModel(engineerBusines.get("样品型号"));
            messageBusiness.setEngineer(engineerusername);
            messageBusiness.setAgreementAmount(AgreementAmount);
            LOG.info("{}，业务信息:{}",engineerBusines.get("合同编号"),messageBusiness);
            return messageBusiness;
        } catch (Exception e){
            LOG.error(e.getMessage());
        }
        return null;
    }

    public List<MessageBusiness> getEngineerMessageBusiness(String engineerName){
//        List<MessageBusiness> byEngineer = messageBusinessRepositories.findByEngineer(engineerName);
        return null;
    }

    /**
     * 获取没有收到款项的业务信息
     * @param engineerBussinessDto
     * @return
     */
    public void getEngineerBusinessInvoice(EngineerBussinessDto engineerBussinessDto){
        List<MessageBusiness> result = null;
        Page<MessageBusiness> allCustomize = null;

        Specification<MessageBusiness> specification = new Specification<MessageBusiness>() {
            @Override
            public Predicate toPredicate(Root<MessageBusiness> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (!engineerBussinessDto.getEngLimsAccount().equals("")){
                    predicateList.add(criteriaBuilder.equal(root.get("engineer"), engineerBussinessDto.getEngLimsAccount()));
                }
                if (!engineerBussinessDto.getInvoiceMoney().equals("")){
                    if(engineerBussinessDto.getInvoiceMoney().equals("1.0")){
                        predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("invoice"), 1.0));
                    }else if (engineerBussinessDto.getInvoiceMoney().equals("0.0")){
                        predicateList.add(criteriaBuilder.equal(root.get("invoice"),engineerBussinessDto.getInvoiceMoney()));
                    }
                }
                // 时间查询
                if (engineerBussinessDto.getValueDate().size() != 0){
                    String startDate = (String)engineerBussinessDto.getValueDate().get(0);
                    String endDate = (String)engineerBussinessDto.getValueDate().get(1);
                    predicateList.add(
                            criteriaBuilder.between(
                                    root.get("startDate").as(Date.class),
                                    DateUtil.parse(startDate.split("T")[0]),
                                    DateUtil.parse(endDate.split("T")[0])
                            )
                    );
                }
                predicateList.add(criteriaBuilder.notLike(root.get("client"),"%中认尚动%"));
                return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };
        // 分页和不分页，这里按起始页和每页展示条数为0时默认为不分页，分页的话按创建时间降序
        try {
            if (engineerBussinessDto.getPage() == 0 && engineerBussinessDto.getSize() == 0) {
                List<BusinessDto> businessDtoList = setBusinessDto(messageBusinessRepositories.findAll(specification));
                engineerBussinessDto.setList(businessDtoList);
            } else {
                allCustomize = messageBusinessRepositories.findAll(specification, PageRequest.of(engineerBussinessDto.getPage() - 1, engineerBussinessDto.getSize()));
                List<BusinessDto> businessDtoList = setBusinessDto(allCustomize.getContent());
                engineerBussinessDto.setList(businessDtoList);
                engineerBussinessDto.setTotal(allCustomize.getTotalElements());
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error("--queryFlowByCondition-- error : ", e);
        }
    }


    public static List<BusinessDto> setBusinessDto(List<MessageBusiness> list){
        List<BusinessDto> businessDtoList = new ArrayList<>();
        for (MessageBusiness messageBusiness:list){
            BusinessDto businessDto = new BusinessDto();
            long betweenDay = DateUtil.between(new Date(), messageBusiness.getEndDate(), DateUnit.DAY);
            if (messageBusiness.getEndDate().getTime() - new Date().getTime() <= 0){
                businessDto.setDateBetween("error");
            }else if (betweenDay <= 5 ){
                businessDto.setDateBetween("warning");
            }else {
                businessDto.setDateBetween("danger");
            }
                businessDto.setContractNo(messageBusiness.getContractNo());
                businessDto.setInvoice(messageBusiness.getInvoice());
                businessDto.setStandard(messageBusiness.getStandard());
                businessDto.setStartDate(DateUtil.format(messageBusiness.getStartDate(),"yyyy-MM-dd"));
                businessDto.setEndDate(DateUtil.format(messageBusiness.getEndDate(),"yyyy-MM-dd"));
                businessDto.setClient(messageBusiness.getClient());
                businessDto.setReportType(messageBusiness.getReportType());
                businessDto.setAgreementAmount(messageBusiness.getAgreementAmount());
                businessDtoList.add(businessDto);
                businessDto.setNature(getNature(messageBusiness.getReportType()));
                businessDto.setRemarks(messageBusiness.getRemarks());
                businessDto.setSampleCategory(messageBusiness.getSampleCategory());
                businessDto.setSampleModel(messageBusiness.getSampleModel());
        }
        return businessDtoList;
    }


    public static String getNature(String report){
        Map<String,String> nature = new HashMap<>();
        nature.put("CCC强制认证-原电器所","CCC强制认证");
        nature.put("委托试验检验报告、型式试验报告（中文）","委托");
        nature.put("监督抽样检测报告","监督抽样");
        nature.put("出具数据","出具数据");
        nature.put("CQC自愿认证-原电器所","CQC自愿认证");
        nature.put("委托试验检验报告、型式试验报告（英文）","委托");
        return nature.get(report);
    }
}
